﻿using AutoMapper;
using Microsoft.Extensions.Logging;
using Step4.Unit7.Model.Entities;
using Step4.Unit7.Service.Dto;
using Step4.Unit7.Service.Dto.Condition;
using Step4.Unit7.Service.utils;
using Step4.Unit7.Service.utils.Snowflake;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;

namespace Step4.Unit7.Service
{
    public class AccountService : IAccountService
    {
        private readonly StepDbContext _dbContext;
        private readonly ILogger<AccountService> _logger;
        private readonly IMapper _mapper;
        private readonly IdWorker _idWorker;

        public AccountService(StepDbContext stepDbContext,
                              ILogger<AccountService> logger,
                              IMapper mapper)
        {
            _dbContext = stepDbContext;
            _logger = logger;
            _mapper = mapper;
            _idWorker = SnowflakeUtil.CreateIdWorker();
        }

        /// <summary>
        /// 搜索
        /// </summary>
        public List<AccountViewModel> Search(AccountRequest? condition)
        {
            // 委托，链式写法
            //var accounts = _dbContext.Accounts.ToList().Select(e => new AccountViewModel()
            //{
            //    Id = e.Id,
            //    AccountState = e.AccountState.ToDescription(),
            //    BankName = e.BankName,
            //    SaleMan = e.SaleMan,
            //    DebtorMoney = e.DebtorMoney,
            //    UpdatedTime = e.UpdatedTime
            //}).Skip((condition.PageIndex - 1) * condition.PageSize).Take(condition.PageSize).ToList(); 

            /*
                Linq 有两种：
                    ①、原始Linq  ，形式类似于sql语句
                    ②、方法Linq  , 存在于EF等orm中，等于将原始Linq封装成方法，参数一般为委托类型
             */


            // EF  "linq联表查询"
            var accounts = from a in _dbContext.Accounts
                           join b in _dbContext.Debtors
                           on a.DebtorId equals b.Id
                           into abtemp
                           from abJoin in abtemp.DefaultIfEmpty()
                           where a.Deleted != 1
                           orderby a.Id descending  // 雪花算法的ID是根据时间生成的，"可以用来排序"
                           select new AccountViewModel
                           {
                               Id = a.Id,
                               AccountState = a.AccountState.ToDescription(),// 使用了枚举的自定义扩展
                               BankName = a.BankName,
                               IdCard = abJoin.IdCard,
                               DebtorName = abJoin.NickName,
                               Phone = abJoin.Phone,
                               DebtorId = a.DebtorId,
                               SaleMan = a.SaleMan,
                               UpdatedTime = a.UpdatedTime,
                               DebtorMoney = a.DebtorMoney,
                               CreatedTime = a.CreatedTime
                           };

            if (!string.IsNullOrEmpty(condition.BankName))
            {
                accounts = accounts.Where(e => e.BankName.Contains(condition.BankName));
            }
            if (!string.IsNullOrEmpty(condition.DebtorName))
            {
                accounts = accounts.Where(e => e.DebtorName.Contains(condition.DebtorName));
            }
            if (condition.AccountState != AccountStateEnum.All)
            {
                accounts = accounts.Where(e => e.AccountState == condition.AccountState.ToDescription());
            }
            // 通过堆栈传值，(两个引用类型指向同一对象可使用堆栈传值)
            condition.Total = accounts.ToList().Count();
            return accounts.Skip((condition.PageIndex - 1) * condition.PageSize).Take(condition.PageSize).ToList();
        }

        /// <summary>
        /// EF添加
        /// </summary>
        void IAccountService.Add(AccountBo bo)
        {
            var account = _mapper.Map<Account>(bo);
            account.Id = _idWorker.NextId(); //雪花算法
            account.AccountState = AccountStateEnum.Wait;
            account.CreatedTime = DateTime.Now;
            var ss = _dbContext.Accounts.Add(account);
            _dbContext.SaveChanges(); //  必须保存更改  "等于告诉程序生成一条sql，并执行"
        }

        /// <summary>
        /// 删除(软)
        /// </summary>
        public void Delete(long id)
        {
            // 假删除 
            var entity = _dbContext.Accounts.FirstOrDefault(e => e.Id == id);
            entity.Deleted = 1;  // 假删除
            entity.UpdatedTime = DateTime.Now;
            _dbContext.SaveChanges();



            // 真删除 (绝对不能出现这样的真删除代码)
            //var account = _dbContext.Accounts.FirstOrDefault(e => e.Id == id);
            //_dbContext.Accounts.Remove(account);
            //_dbContext.SaveChanges();
        }

        /// <summary>
        /// 获取单个AccountViewModel
        /// </summary>
        public AccountUpdateBo GetModel(long Id)
        {
            var account = _dbContext.Accounts.FirstOrDefault(e => e.Id == Id);
            return _mapper.Map<AccountUpdateBo>(account);
        }

        /// <summary>
        /// 改
        /// </summary>
        public void Update(AccountUpdateBo bo)
        {
            var account = _dbContext.Accounts.FirstOrDefault(p => p.Id == bo.Id);
            account.AccountState = bo.AccountState;
            account.SaleMan = bo.SaleMan;
            account.UpdatedTime = DateTime.Now;
            _dbContext.SaveChanges();
        }

        /// <summary>
        /// 获取站务人
        /// </summary>
        public List<DebtorViewModel> GetDebtors()
        {
            var list = _dbContext.Debtors.Where(e => e.Deleted == 0).ToList();
            return _mapper.Map<List<DebtorViewModel>>(list);
        }
    }
}
